package com.morgan.recyclerviewdemo.view

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.os.Bundle
import android.os.Parcelable
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.morgan.recyclerviewdemo.R
import com.morgan.recyclerviewdemo.entity.IClassificateTag
import com.morgan.recyclerviewdemo.utils.DeviceUtil

/**
 * 右侧导航栏
 */
class VerticalNavigationBar(context : Context, attrs : AttributeSet?, defStyleAttr : Int) : View(context, attrs, defStyleAttr) {
    var mLetters : List<IClassificateTag>? = null

    var mNormalBackgroundColor : Int = Color.LTGRAY
    var mPressBackgroundColor : Int = Color.GRAY
    var mBackgroundColor = mNormalBackgroundColor

    var mLettersFontSize : Float = DeviceUtil.sp2Px(context, 10f).toFloat()

    var mLetterNormalTextColor = Color.BLACK
    var mLetterPressTextColor = Color.WHITE
    var mLetterTextColor = mLetterNormalTextColor

    private val mTextBounds : Rect = Rect()
    private val mPaint : Paint = Paint(Paint.ANTI_ALIAS_FLAG)

    private var mMaxContentWidth = 0
    private var mMaxContentHeight = 0
    private var mItemPaddingTop = 0
    private var mItemPaddingBottom = 0
    private var mWidth = 0
    private var mHeight = 0
    private var mItemHeight = 0

    private var mPressListener : OnPressMoveListener? = null
    private val mBackgroundRect  = Rect()

    private var mDrawTextList : ArrayList<String>? = null

    init {

        val a = context.obtainStyledAttributes(attrs, R.styleable.VerticalNavigationBar, defStyleAttr, 0)

        mNormalBackgroundColor = a.getColor(R.styleable.VerticalNavigationBar_normalBackgroundColor, Color.LTGRAY)
        mPressBackgroundColor = a.getColor(R.styleable.VerticalNavigationBar_pressBackgroundColor, Color.GRAY)
        mLettersFontSize = a.getDimension(R.styleable.VerticalNavigationBar_lettersFontSize, DeviceUtil.sp2Px(context, 10f).toFloat())
        mLetterNormalTextColor = a.getColor(R.styleable.VerticalNavigationBar_letterNormalTextColor, Color.BLACK)
        mLetterPressTextColor = a.getColor(R.styleable.VerticalNavigationBar_letterPressTextColor, Color.WHITE)

        mBackgroundColor = mNormalBackgroundColor
        mLetterTextColor = mLetterNormalTextColor

        a.recycle()
    }

    interface OnPressMoveListener {
        fun onPress(letter : IClassificateTag, position : Int)
        fun onPressEnd()
    }

    constructor(context : Context, attrs : AttributeSet) : this(context, attrs, 0) {
    }

    constructor(context : Context) : this(context, null, 0) {
    }

    fun setUpWith(letters : List<IClassificateTag>, listener : OnPressMoveListener) {
        mLetters = letters
        mPressListener = listener
        tryToGetDrawTextList()
        measureItemHeight()
        invalidate()
    }

    private fun tryToGetDrawTextList() {
        if (mLetters == null || mLetters!!.isEmpty()) {
            return
        }
        mLetters?.let {
            if (mDrawTextList == null) {
                mDrawTextList = ArrayList()
            } else {
                mDrawTextList!!.clear()
            }
            val rang = 0..it.size - 1
            for (i in rang) {
                if (!mDrawTextList!!.contains(it[i].getTag())) {
                    mDrawTextList!!.add(it[i].getTag())
                }

            }
            val s = mDrawTextList!![mDrawTextList!!.size - 1]
        }

    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

        var resultWidth = 0

        val wideMode = MeasureSpec.getMode(widthMeasureSpec)
        val wideSize = MeasureSpec.getSize(widthMeasureSpec)
        val defaultWidth = suggestedMinimumWidth
        measureContentSize()
        when (wideMode) {
            MeasureSpec.EXACTLY -> resultWidth = wideSize
            MeasureSpec.AT_MOST -> resultWidth = Math.min(wideSize, mMaxContentWidth + paddingLeft + paddingRight)
            MeasureSpec.UNSPECIFIED -> resultWidth = Math.max(defaultWidth, mMaxContentWidth)
        }

        var resultHeight = 0
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)
        val heightSize = MeasureSpec.getSize(heightMeasureSpec)
        val defaultHeight = suggestedMinimumHeight
        when (heightMode) {
            MeasureSpec.EXACTLY -> resultHeight = heightSize
            MeasureSpec.AT_MOST -> resultHeight = Math.min(heightSize, mMaxContentHeight + paddingTop + paddingBottom)
            MeasureSpec.UNSPECIFIED -> resultHeight = Math.max(defaultHeight, mMaxContentHeight)
        }

        setMeasuredDimension(resultWidth, resultHeight)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        mWidth = w
        mHeight = h
        measureItemHeight()
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
//        return super.onTouchEvent(event)
        event?.let {
            when (it.action) {
                MotionEvent.ACTION_DOWN  -> {
                    mBackgroundColor = mPressBackgroundColor
                    mLetterTextColor = mLetterPressTextColor
                    invalidate()
                    return true
                }
                MotionEvent.ACTION_MOVE -> {
                    if (mItemHeight <= 0) {
                        return super.onTouchEvent(event)
                    }
                    val pressPosition = ((event.y - paddingTop) / mItemHeight).toInt()
                    callbackPressListener(pressPosition)
                    return true
                }
                MotionEvent.ACTION_UP,
                MotionEvent.ACTION_CANCEL -> {
                    mBackgroundColor = mNormalBackgroundColor
                    mLetterTextColor = mLetterNormalTextColor
                    invalidate()
                    mPressListener?.onPressEnd()
                    return true
                }
                else -> {
//                    mBackgroundColor = mNormalBackgroundColor
//                    mLetterTextColor = mLetterNormalTextColor
//                    invalidate()
//                    mPressListener?.onPressEnd()
//                    return true
                }
            }
        }
        return super.onTouchEvent(event)
    }
    override fun onDraw(canvas: Canvas?) {
        if (mDrawTextList == null || mDrawTextList!!.isEmpty()) {
            return
        }
        if (mItemHeight <= 0) {
            measureItemHeight()
        }
        if (mItemHeight <= 0) {
            return
        }

        val paddingLeft = paddingLeft
        val paddingRight = paddingRight
        val paddingTop = paddingTop
        val paddingBottom = paddingBottom

        mBackgroundRect.left = paddingLeft
        mBackgroundRect.top = paddingTop
        mBackgroundRect.right = mWidth - paddingRight
        mBackgroundRect.bottom = mHeight - paddingBottom

        mPaint.color = mBackgroundColor
        canvas!!.drawRect(mBackgroundRect, mPaint)

        mDrawTextList?.let {

            mPaint.textSize = mLettersFontSize
            mPaint.color = mLetterTextColor
            val rang = 0 ..it.size - 1
            for (i in rang) {
                val text = it[i]
                val drawTextX = paddingLeft + (mWidth - paddingLeft - paddingRight)/2 - mPaint.measureText(text)/2
                val fontMetrics = mPaint.fontMetrics
                val baseline = (mItemHeight - fontMetrics.bottom - fontMetrics.top) / 2 //计算出在每格index区域，竖直居中的baseLine值
                canvas.drawText(text, drawTextX, paddingTop + mItemHeight * i + baseline, mPaint)
            }

        }
    }

    private fun callbackPressListener(pressPosition: Int) {
        if (mDrawTextList == null
            || mDrawTextList!!.isEmpty()
            || mLetters == null
            || mLetters!!.isEmpty()
            || mPressListener == null) {
            return
        }
        var position = pressPosition
        if (pressPosition < 0) {
            position = 0
        } else if (pressPosition >= mDrawTextList!!.size) {
            position = mDrawTextList!!.size - 1
        }
        val targetTag = mDrawTextList!![position]
        val range = 0 .. mLetters!!.size -1
        for (i in range) {
            if (targetTag.equals(mLetters!![i].getTag())) {
                mPressListener!!.onPress(mLetters!![i], i)
                break
            }
        }

    }

    override fun onSaveInstanceState(): Parcelable? {
//        return super.onSaveInstanceState()
        if (mLetters == null || mLetters!!.isEmpty()) {
            return super.onSaveInstanceState()
        }
        val params = Bundle()
        params.putParcelableArrayList("letter", ArrayList(mLetters!!))
        return params
    }

    override fun onRestoreInstanceState(state: Parcelable?) {
        state?.let {
            if (it is Bundle) {
                val params = it
                mLetters = params.getParcelableArrayList("letter")
                tryToGetDrawTextList()
            }
        }
        super.onRestoreInstanceState(state)
    }

    private fun measureItemHeight() {
        if (mDrawTextList == null || mDrawTextList!!.isEmpty()) {
            return
        }
        mItemHeight = (mHeight - paddingTop - paddingBottom) / mDrawTextList!!.size
    }

    private fun measureContentSize(){
        if (mDrawTextList == null || mDrawTextList!!.isEmpty()) {
            return
        }
        mPaint.textSize = mLettersFontSize
        mDrawTextList?.let {
            var maxWidth = 0f
            var maxItemHeight = 0f
            val rang = 0..it.size - 1
            for (i in rang) {
                val letter = it[i]
                maxWidth = Math.max(maxWidth, mPaint.measureText(letter))
                mPaint.getTextBounds(letter, 0, letter.length, mTextBounds)
                maxItemHeight = Math.max(maxItemHeight, mTextBounds.height().toFloat())
            }
            mMaxContentWidth = maxWidth.toInt()
            mMaxContentHeight = (maxItemHeight.toInt() + mItemPaddingTop + mItemPaddingBottom) * it.size
        }
    }

}